#include "user_run.h"
#include "app_fault.h"
#include "golink_floor_fault.h"
#include "golink_floor_info.h"
#include "golink_show_info.h"
#include "hal_key.h"
#include "hal_motor.h"
#include "hal_system_status.h"
#include "hal_floor.h"
#include "hal_tty.h"
#include "user_floor_ctrl.h"
#include <stdint.h>

#include "FreeRTOS.h"
#include "task.h"
#include "floor_sys.h"

uint8_t jt_event = 0;

#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))






void user_device_init() {

//    //@todo 急停 和 门锁
//    rcu_periph_clock_enable(JT_KEY_RCU);

//    gpio_mode_set(JT_KEY_BASE,GPIO_MODE_INPUT,GPIO_PUPD_PULLDOWN,
//            JT_KEY_PIN | DOOR_CHECK_PIN);

//    //平层，上限位，下限位
//    rcu_periph_clock_enable(FLAT_FLOOR_RCU);
//    gpio_mode_set(FLAT_FLOOR_BASE,GPIO_MODE_INPUT,GPIO_PUPD_PULLDOWN,
//            FLAT_FLOOR_PIN | UPPER_LIMIT_PIN | LOWER_LIMIT_PIN);
}

uint8_t get_door_lock() {

//    if(gpio_input_bit_get(DOOR_CHECK_BASE,DOOR_CHECK_PIN))
//        return 1;
    return 0;
}

uint8_t get_flat_floor() {

//    if(gpio_input_bit_get(FLAT_FLOOR_BASE,FLAT_FLOOR_PIN))
//        return 1;
    return 0;
}

uint8_t get_upper_limit() {
//    if(gpio_input_bit_get(UPPER_LIMIT_BASE,UPPER_LIMIT_PIN))
//        return 1;
    return 0;
}

uint8_t get_lower_limit() {
//    if(gpio_input_bit_get(LOWER_LIMIT_BASE,LOWER_LIMIT_PIN))
//        return 1;
    return 0;
}

void do_fault_loop(uint8_t fault) {

    g_motor_.ctrl_run(0);
	
	if(fault != g_floor_ctrl_.fault_) {
		g_floor_ctrl_.fault_ = fault;
		//@todo send display fault!!!!
	}
	
    //@todo send fault message!!
	
	//清空任务！！
    g_floor_ctrl_.target_floor_ = -1;
    g_floor_ctrl_.req_floor_ = -1;
}

void do_stop_loop() {

    g_motor_.ctrl_run(0);
    //@todo display 紧急停止
    //@todo send 紧急停止 message！！

    //清空任务！！
    g_floor_ctrl_.target_floor_ = -1;
    g_floor_ctrl_.req_floor_ = -1;
}

void do_test_loop() {
    
    //@todo key = key_scan();
}

int do_normal_init() {
    
    if(get_flat_floor()) {
        golink_send_floor_fault(0,GOLINK_CTRL_NOT_READY);
        //@todo display NOT_READY error!
        golink_send_floor_info(GOLINK_REQUEST_STOP_FLOOR,0);
        return 1;
    } else {
        if(get_door_lock()) {
            //@todo display NOT_READY error!
            golink_send_floor_fault(0,GOLINK_CTRL_NOT_READY);
            if(get_lower_limit()) {
                g_motor_.ctrl_up();
                g_motor_.ctrl_run(1);
            } else {
                g_motor_.ctrl_down();
                g_motor_.ctrl_run(1); 
            }
        } else {
            //@todo display NOT lock error!
            golink_send_floor_fault(0,GOLINK_ERR_DOOR_NOT_LOCK);
        }
    }

    return 0;
}

int check_floor_reach() {

    if(g_floor_ctrl_.req_floor_ != -1) {
        uint8_t run_state,down_state;
        g_motor_.get_status(&run_state,&down_state);

        if(run_state) {
            uint8_t target_floor = -1;
            if(down_state == MOTOR_STATE_DOWN) {
                target_floor = min(g_floor_ctrl_.req_floor_,g_floor_ctrl_.target_floor_);
                g_floor_ctrl_.req_floor_ = -1;
            } else {
                target_floor = max(g_floor_ctrl_.req_floor_,g_floor_ctrl_.target_floor_);
            }

            if(target_floor != g_floor_ctrl_.target_floor_) {
                g_floor_ctrl_.target_floor_ = target_floor;
                golink_send_floor_show(GOLINK_CHANGE_DES_CMD,0,target_floor);
            }
        } 
    }

    if(get_flat_floor()) {
        if(g_floor_ctrl_.cur_floor_ == g_floor_ctrl_.target_floor_) {
            return 1;
        } else {
            golink_send_floor_show(GOLINK_CHANGE_SRC_CMD,g_floor_ctrl_.cur_floor_,0);
        }
    }

    uint32_t time = (xTaskGetTickCount() - g_floor_ctrl_.time_ticks_) / 1000;
    if(g_floor_ctrl_.run_sec_ != time) {
        //@todo show !!!!
    }

    return 0;
}

int do_check_wait_standby() {

    if(get_flat_floor()) {
        g_motor_.ctrl_run(0);
        golink_send_floor_info(GOLINK_REQUEST_STOP_FLOOR,0);
        return 1;
    }

    return 0;
}

int get_request_task() {

    int ret = 0;
    if(g_floor_ctrl_.req_floor_ != -1) {
        
        //当门锁没有锁的情况下无法响应所有的电梯请求直接退出
        if(!get_door_lock()) {
            g_floor_ctrl_.req_floor_ = -1;
            return ret;
        }
    
        if(g_floor_ctrl_.req_floor_ != g_floor_ctrl_.cur_floor_) {
            g_floor_ctrl_.target_floor_ = g_floor_ctrl_.req_floor_;

            g_floor_ctrl_.time_ticks_ = xTaskGetTickCount();
            g_floor_ctrl_.run_sec_ = 0;

            if(g_floor_ctrl_.target_floor_ > g_floor_ctrl_.cur_floor_) {
                golink_send_floor_show(GOLINK_UP_CMD,g_floor_ctrl_.cur_floor_,g_floor_ctrl_.target_floor_);
                g_motor_.ctrl_up();

                //@todo display running time and up & down
            } else {
                golink_send_floor_show(GOLINK_DOWN_CMD,g_floor_ctrl_.cur_floor_,g_floor_ctrl_.target_floor_);
                g_motor_.ctrl_down();
                
                //@todo display running time and up & down
            }
            g_motor_.ctrl_run(1);

            ret = 1;
        }
        g_floor_ctrl_.req_floor_ = -1;
    }

    return ret;
}

void do_normal_loop(uint8_t param) {

    switch(g_floor_ctrl_.state_) {
        case FLOOR_STATE_INIT:
            if(do_normal_init())
                g_floor_ctrl_.state_ = FLOOR_STATE_IDLE;
            else
                g_floor_ctrl_.state_ = FLOOR_STATE_WAIT_STANDBY;
            break;
        case FLOOR_STATE_WAIT_STANDBY:
            if(do_check_wait_standby()) {
                if(g_floor_ctrl_.cur_floor_ == -1) {
                    g_floor_ctrl_.state_ = FLOOR_STATE_WAIT_READY;
                } else {
                    golink_send_floor_info(GOLINK_STOP_FLOOR,g_floor_ctrl_.cur_floor_);
                    g_floor_ctrl_.state_ = FLOOR_STATE_IDLE;
                }
            }
            break;
        case FLOOR_STATE_WAIT_READY:
            if(g_floor_ctrl_.cur_floor_ != -1) {
                golink_send_floor_info(GOLINK_STOP_FLOOR,g_floor_ctrl_.cur_floor_);
                g_floor_ctrl_.state_ = FLOOR_STATE_IDLE;
            }
            break;
        case FLOOR_STATE_IDLE:
            if(get_request_task()) {
                g_floor_ctrl_.state_ = FLOOR_STATE_RUNNING;
            }
            break;
        case FLOOR_STATE_RUNNING:
            if(check_floor_reach() == 1) {
                golink_send_floor_show(GOLINK_STOP_FLOOR,g_floor_ctrl_.cur_floor_,0);
                g_motor_.ctrl_run(0);
                g_floor_ctrl_.state_ = FLOOR_STATE_IDLE;
            }
            break;
        case FLOOR_STATE_STOP:
            do_stop_loop();
            break;
        case FLOOR_STATE_TEST:
            do_test_loop();
            break;
		case FLOOR_STATE_FAULT:
			do_fault_loop(param);
			break;
        default:
            break;
    }
}

int main_loop() {

	uint8_t target_state_ = g_floor_ctrl_.state_;

	if(g_test_.test_mode()) {
		target_state_ = FLOOR_STATE_TEST;
	}
		
	//check  fault 错误
	uint8_t fault = g_sys_.system_state();
	if(fault != SYS_FAULT_NORMAL) {
		if(fault == SYS_FAULT_RELAY) {
			fault = APP_FAULT_TERM_RELAY;
		} else {
			fault = APP_FAULT_BAND_BREAK;
		}
		target_state_ = FLOOR_STATE_FAULT;
	}
	
	if(g_motor_.get_phase_sequence()) {
		fault = APP_FAULT_SEQUENCE;
		target_state_ = FLOOR_STATE_FAULT;
	}
	
	if(g_floor_node_.jt_key()) {
		g_floor_ctrl_.state_ = FLOOR_STATE_STOP; 
	}
	 
	if(target_state_ != g_floor_ctrl_.state_) {
		g_motor_.ctrl_run(0);
		g_floor_ctrl_.state_ = target_state_;
	}
	
	do_normal_loop(fault);

    return 0;
}

